/*************************************************************************** 
 * (c) 2006 Dmitry Osinovsky, osdmsoftware@gmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU Lesser General Public License as        *
 *   published by the Free Software Foundation; either version 2 of the    *
 *   License, or (at your option) any later version.                       *
 *                                                                         *
 ***************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Drawing.Imaging;
using System.Resources;

namespace OsdmSoftware.PocketPicture
{
    public class LineTool: PaintTool
    {
        bool HasFirstPoint;
        Point undoBitmapPoint;
        Bitmap undoBitmap;

        public LineTool()
            : base("Draw straight line")
        {
            ParentName = "Contours";
        }

        public override void SelectTool()
        {
            Form.HintLabel.Text = "Select first point";
            HasFirstPoint = false;
        }

        protected virtual void DoDrawLine(Graphics gr, int x1, int y1, int x2, int y2)
        {
            gr.DrawLine(new Pen(Form.PaletteSelectedColor, Form.PenWidth), x1, y1, x2, y2);
        }

        public override void MouseDown(int x, int y)
        {
            /*if (HasFirstPoint)
            {
                Trace.Assert(Form.BitmapZoomer.SelectedPoints.Count == 1, "Must be one and only one selected point");
                Point p = Form.BitmapZoomer.SelectedPoints[0];
                Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);
                DoDrawLine(gr, p.X, p.Y, x, y);
                gr.Dispose();
                Form.BitmapZoomer.SelectedPoints.Clear();
                Form.BitmapZoomer.Refresh();
                Form.PushToUndo();
                //HasFirstPoint = false;
                SelectTool();
            }
            else
            {
                Form.BitmapZoomer.AddSelectedPoint(x, y);
                HasFirstPoint = true;
                Form.HintLabel.Text = "Select second point";
            }*/

            Form.BitmapZoomer.AddSelectedPoint(x, y);
            HasFirstPoint = true;
            Form.HintLabel.Text = "Select second point";
        }

        public override void MouseMove(int x, int y)
        {
            if (HasFirstPoint)
            {
                Trace.Assert(Form.BitmapZoomer.SelectedPoints.Count == 1, "Must be one and only one selected point");
                Point p = Form.BitmapZoomer.SelectedPoints[0];

                Graphics gr = Graphics.FromImage(Form.BitmapZoomer.Bitmap);

                int updateX1 = Int32.MaxValue, updateY1 = Int32.MaxValue, updateX2 = Int32.MinValue, updateY2 = Int32.MinValue;
                if (undoBitmap != null)
                {
                    gr.DrawImage(undoBitmap, new Rectangle(undoBitmapPoint.X, undoBitmapPoint.Y, undoBitmap.Width, undoBitmap.Height), new Rectangle(0, 0, undoBitmap.Width, undoBitmap.Height), GraphicsUnit.Pixel);
                    updateX1 = undoBitmapPoint.X;
                    updateY1 = undoBitmapPoint.Y;
                    updateX2 = undoBitmapPoint.X + undoBitmap.Width;
                    updateY2 = undoBitmapPoint.Y + undoBitmap.Height;
                    undoBitmap.Dispose();
                    undoBitmap = null;
                }
                undoBitmap = new Bitmap(Math.Abs(p.X - x) + 2 * Form.PenWidth + 1, Math.Abs(p.Y - y) + 2 * Form.PenWidth + 1, PixelFormat.Format32bppRgb);
                undoBitmapPoint = new Point(Math.Max(Math.Min(p.X, x) - Form.PenWidth, 0), Math.Max(Math.Min(p.Y, y) - Form.PenWidth, 0));
                Graphics gr1 = Graphics.FromImage(undoBitmap);
                gr1.DrawImage(Form.BitmapZoomer.Bitmap, new Rectangle(0, 0, undoBitmap.Width, undoBitmap.Height), new Rectangle(undoBitmapPoint.X, undoBitmapPoint.Y, undoBitmap.Width, undoBitmap.Height), GraphicsUnit.Pixel);
                gr1.Dispose();

                DoDrawLine(gr, p.X, p.Y, x, y);
                updateX1 = Math.Min(undoBitmapPoint.X, updateX1);
                updateY1 = Math.Min(undoBitmapPoint.Y, updateY1);
                updateX2 = Math.Max(undoBitmapPoint.X + undoBitmap.Width, updateX2);
                updateY2 = Math.Max(undoBitmapPoint.Y + undoBitmap.Height, updateY2);

                Form.BitmapZoomer.InvalidateBitmap(updateX1, updateY1, updateX2 - updateX1, updateY2 - updateY1);
                gr.Dispose();

                Form.HintLabel.Text = "(" + p.X.ToString() + ", " + p.Y.ToString() + ") - (" + x.ToString() + ", " + y.ToString() + ")";
                Form.HintLabel.Refresh();
            }
        }

        public override void MouseUp()
        {
            if (HasFirstPoint)
            {
                if (undoBitmap != null)
                {
                    undoBitmap.Dispose();
                    undoBitmap = null;
                }
                Form.BitmapZoomer.SelectedPoints.Clear();
                Form.BitmapZoomer.Refresh();
                Form.PushToUndo();
                //HasFirstPoint = false;
                SelectTool();
            }
        }

        public override void Cancel()
        {
            if (HasFirstPoint)
            {
                undoBitmap.Dispose();
                undoBitmap = null;
                Form.BitmapZoomer.SelectedPoints.Clear();
                Form.BitmapZoomer.Refresh();
                SelectTool();
            }
            base.Cancel();
        }

        public override bool CanCancel()
        {
            return HasFirstPoint;
        }
    }

    public class RectangularTool: LineTool
    {
        public RectangularTool()
        {
            this.Hint = "Draws rectangle";
        }

        protected virtual void DoDraw(Graphics gr, int x1, int y1, int x2, int y2)
        {
        }

        protected override void DoDrawLine(Graphics gr, int x1, int y1, int x2, int y2)
        {
            int nx1 = Math.Min(x1, x2);
            int ny1 = Math.Min(y1, y2);
            int nx2 = Math.Max(x1, x2);
            int ny2 = Math.Max(y1, y2);
            DoDraw(gr, nx1, ny1, nx2, ny2);
        }
    }

    public class EllipseTool: RectangularTool
    {
        public EllipseTool()
        {
            this.Hint = "Draws ellipse";
        }

        protected override void DoDraw(Graphics gr, int x1, int y1, int x2, int y2)
        {
            int w = x2 - x1;
            int h = y2 - y1;
            gr.DrawEllipse(new Pen(Form.PaletteSelectedColor, Form.PenWidth), x1, y1, w, h);
        }
    }

    public class FilledEllipseTool: RectangularTool
    {
        public FilledEllipseTool()
        {
            ParentName = "Contours";
            this.Hint = "Draws filled ellipse";
        }

        protected override void DoDraw(Graphics gr, int x1, int y1, int x2, int y2)
        {
            int w = x2 - x1;
            int h = y2 - y1;
            gr.FillEllipse(new SolidBrush(Form.PaletteSelectedColor), x1, y1, w, h);
        }
    }

    public class RectangleTool: RectangularTool
    {
        protected override void DoDraw(Graphics gr, int x1, int y1, int x2, int y2)
        {
            int w = x2 - x1;
            int h = y2 - y1;
            gr.DrawRectangle(new Pen(Form.PaletteSelectedColor, Form.PenWidth), x1, y1, w, h);
        }
    }

    public class FilledRectangleTool: RectangularTool
    {
        public FilledRectangleTool()
        {
            ParentName = "Contours";
            this.Hint = "Draws filled rectangle";
        }

        protected override void DoDraw(Graphics gr, int x1, int y1, int x2, int y2)
        {
            int w = x2 - x1;
            int h = y2 - y1;
            gr.FillRectangle(new SolidBrush(Form.PaletteSelectedColor), x1, y1, w + 1, h + 1);
        }
    }

}